package me.zhenqu.redis;

import me.zhenqu.redis.utils.CacheCoder;
import me.zhenqu.redis.utils.CoderFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created at 11-10-17
 *
 * @author yonghui.chen
 */
public class RedisArrayCache<T> extends GenericCache<T[]> {
    private CacheCoder<T[]> coder;
    private int defaultExpire;
    private String category;
    private RedisOperator operator;

    public RedisArrayCache(RedisOperator operator, String category, int defaultExpire,
                           Class<?> clazz) {
        this.coder = CoderFactory.getArrayCoder(clazz);
        this.defaultExpire = defaultExpire;
        this.category = "rca_" + category;
        this.operator = operator;
    }

    public T[] get(String key) {
        byte[] v = operator.getBytes(category, key);
        try {
            return v == null || v.length == 0 ? null : coder.decode(v);
        } catch (Exception e) {
            return null;
        }
    }

    public boolean put(String key, T[] value) {
        if (value == null) operator.removeCategory(category, key);
        else return operator.set(category, key, coder.encode(value), defaultExpire);
        return true;
    }

    public void mput(Map<String, T[]> values) {
        Map<String, byte[]> params = new HashMap<String, byte[]>(values.size());
        for (Map.Entry<String, T[]> entry : values.entrySet()) {
            params.put(entry.getKey(), coder.encode((T[]) entry.getValue()));
        }

        operator.mset(category, params, defaultExpire);
    }

    public Map<String, T[]> mget(List<String> keys) {
        Map<String, byte[]> map = operator.multiGetBytes(category, keys);
        Map<String, T[]> ret = new HashMap<String, T[]>(map.size());
        for (Map.Entry<String, byte[]> entry : map.entrySet()) {
            ret.put(entry.getKey(), coder.decode(entry.getValue()));
        }
        return ret;
    }

    @Override
    public boolean put(String key, T[] value, int timeoutSeconds) {
        if (value == null) operator.removeCategory(category, key);
        else return operator.set(category, key, coder.encode(value), timeoutSeconds);
        return true;
    }

    @Override
    public void mput(Map<String, T[]> values, int timeoutSeconds) {
        Map<String, byte[]> params = new HashMap<String, byte[]>(values.size());
        for (Map.Entry<String, T[]> entry : values.entrySet()) {
            params.put(entry.getKey(), coder.encode((T[]) entry.getValue()));
        }

        operator.mset(category, params, timeoutSeconds);
    }

    @Override
    public void remove(String key) {
        operator.setExpire(category, key, 0);
    }
}
